<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>10-作用域的理解</title>
</head>

<body>
    <script>
        /*
            两种作用域
                编程界一共分为两种作用域
                    动态作用域
                        作用域和代码定义的位置无关，和代码调用的位置有关
                    词法作用域（静态作用域）
                        作用域和代码定义的位置有关，和代码调用的位置无关
            概念：
                变量起作用的范围
                约束变量查找使用的范围
                注意：js属于词法作用域（静态作用）
            作用域作用：
                隔离变量，防止变量冲突(可以在不同作用域内定义同名的变量)
            作用域分类：
                全局作用域
                    <script>中间的代码，这块区域就是全局作用域
                    扩展：js引擎在解析我们的代码的时候，会把script标签里的代码放到一个函数里去执行，所以全局作用域又称为全局函数作用域
                局部作用域（函数作用域）
                    我们创建函数的时候，就会产一个局部作用域，局部作用域里的代码，外侧访问不到
                块级作用域
                    es6新增的作用域，使用let/const定义变量的时候就会产生一个块级作用域
            预解析
                变量提升
                    使用var定义的变量，会将变量标识提升，变量赋值还留在原位置
                    var a = 10
                    var a;就是标识
                    a = 10 是赋值
                函数提升
                    会把整个函数提升到最上面
                提升优先级
                    会优先提升所有的函数,然后再提升用var声明的变量
                    如果函数名和变量名冲突，变量名将被忽略
                提升的位置
                    当前作用域的最上面，不会穿透作用域
            形参默认值：
                注意：函数定义参数，其实定义的就是一个局部变量，只不过这个变量不需要我们用var声明
                使用es6的语法，给参数赋默认值，如果给参数加上默认值，就会多产生一个块级作用域，函数内部所有的代码，都会在块级作用域中执行
                如果有形参默认值，形参默认值的变量名和函数体内部的变量名重名，那形参默认值的值，两者都有份，只不过两个是不同的变量
                

        */


        // function fn(){
        //     var x;
        //     var b;
        //     console.log(b)
        //     x = 30
        //    b = 30
        //     console.log(b)
        // }
        // fn(10)

        // var a = 20
        // function fn(a,b=10){
        //     var x = 10;
        //     console.log(x,a,b)
        // }

        // fn(10)
        // console.log(a)

        // var fn
        // var fn;

        // fn = function () { }

        // console.log(fn)


        // function fn() {
        //     var a
        //     console.log(a)
        //     a = 10
        // }
        // fn();
        // var a = 20
        // function fn() {
        //     var a = 30
        //     a = 40
        // }
        // console.log(a)

        // var a = 10
        // function fn() {
        //     console.log(a)
        // }
        // function fn2() {
        //     var a = 20
        //     fn()
        // }
        // fn2()
        // 1 3 2 1 

        // undefined 3 2 3
        // var x = 1;
        // function fn(
        //     x,
        //     y = function () {
        //         x = 3;
        //         console.log('two', x);
        //     }
        // ) {
        //     console.log('one', x);
        //     var x = 2;
        //     y();
        //     console.log('three', x);
        // }
        // fn();
        // console.log('four', x);

        //   undefined 3 2 3
        // var x = 1;
        // function fn(
        //     xx,
        //     y = function () {
        //         x = 3;
        //         console.log("two", x);
        //     }
        // ) {
        //     console.log("one", x);
        //     var x = 2;
        //     y();
        //     console.log("three", x);
        // }
        // fn();
        // console.log("four", x);

        // 4 3 2 1
        var x = 1;
        function fn(
            x = 4,
            y = function () {
                x = 3;
                console.log("two", x);
            }
        ) {
            console.log("one", x);
            var x = 2;
            y();
            console.log("three", x);
        }
        fn();
        console.log("four", x);

    </script>
</body>

</html>